package model

import (
	"database/sql"
	"github.com/jmoiron/sqlx"
	"github.com/lionsoul2014/ip2region/binding/golang/ip2region"
	"github.com/pkg/errors"
	"strconv"
	"strings"
	"zimuzu_cvn_web_api/config"
	"zimuzu_cvn_web_api/pkg/e"
	"zimuzu_cvn_web_api/pkg/errno"
)

type FixedTWFlows struct {
	NodeId string `form:"node_id" json:"node_id"`
	Date   string `form:"date" json:"date"`
	Hour   string `form:"hour" json:"hour"`
}

type YXFlowsResponse struct {
	Code   int    `form:"code" json:"code"`
	Action string `form:"action" json:"action"`
	Result *YxResult
}
type YxResultPagination struct {
	Page     int   `form:"page" json:"page"`
	PageSize int   `form:"pageSize" json:"pageSize"`
	Total    int64 `form:"total" json:"total"`
}
type NodeMacModel struct {
	NodeId int64  `db:"node_id,omitempty" form:"node_id" json:"node_id,omitempty"`
	Uid    int64  `db:"uid,omitempty" form:"uid" json:"uid,omitempty"`
	Name   string `db:"name,omitempty" form:"name" json:"name,omitempty"`
}
type YxFlowData struct {
	Node  string  `form:"node" json:"node"`
	Time  string  `form:"time" json:"time"`
	Value float64 `form:"value" json:"value"`
}
type YxResult struct {
	Pagination *YxResultPagination
	FlowData   []*YxFlowData
}

type YXInfoResponse struct {
	Code   int    `form:"code" json:"code"`
	Action string `form:"action" json:"action"`
	Result *YxInfoResult
}
type YxInfoResult struct {
	Pagination *YxResultPagination
	NodeData   []*YxInfoData
}
type YxInfoData struct {
	LastOnlineTime string  `form:"lastOnlineTime" json:"lastOnlineTime"`
	DiskUsed       float64 `form:"diskUsed" json:"diskUsed"`
	Node           string  `form:"node" json:"node"`
	Ip             string  `form:"ip" json:"ip"`
	Status         string  `form:"status" json:"status"`
	DiskTotal      float64 `form:"diskTotal" json:"diskTotal"`
	DiskAvail      float64 `form:"diskAvail" json:"diskAvail"`
	OnlineTime     int     `form:"onlineTime" json:"onlineTime"`
}

// 获取到结点信息
type MgNodeResponse struct {
	NodeId            int64  `db:"node_id" form:"node_id" json:"node_id"`
	Sn                string `db:"sn" form:"sn" json:"sn"`
	Mac               string `db:"mac" form:"mac" json:"mac"`
	PublicIp          string `db:"public_ip" form:"public_ip" json:"public_ip"`
	Isp               string `db:"isp" form:"isp" json:"isp"`
	HistoryOnlineTime string `db:"history_online_time" form:"history_online_time" json:"history_online_time"`
}

type MgNodeInfoResponse struct {
	NodeId            int64  `db:"node_id" form:"node_id" json:"node_id"`
	Uid               int64  `db:"uid" form:"uid" json:"uid"`
	Type              int    `db:"type" form:"type" json:"type"`
	Sn                string `db:"sn" form:"sn" json:"sn"`
	Mac               string `db:"mac" form:"mac" json:"mac"`
	HistoryOnlineTime string `db:"history_online_time" form:"history_online_time" json:"history_online_time"`
	TokenStatus       int    `db:"token_status" form:"token_status" json:"token_status"`
	Batch             int    `db:"batch" form:"batch" json:"batch"`
}

type MgUserProfitsResponse struct {
	Uid    int64   `db:"uid"  form:"uid" json:"uid"`
	NodeId int64   `db:"node_id" form:"node_id" json:"node_id"`
	Up     float64 `db:"up"   form:"up" json:"up"`
	Batch  int     `db:"batch" form:"batch" json:"batch"`
}

type MgUserPaymentModel struct {
	Id   int64   `db:"id"  form:"id" json:"id"`
	Uid  int64   `db:"uid"  form:"uid" json:"uid"`
	Up   float64 `db:"up"   form:"up" json:"up"`
	CVNT float64 `db:"cvnt" form:"cvnt" json:"cvnt"`
	Type int     `db:"type" form:"type" json:"type"`
}

func GetMgNodeInfoByUidS(Uid int64, Keyword string, Way int) (NodeInfo MgNodeResponse, err error) {

	switch Way {
	case 1: //1:PC
		err = sqlx.Get(config.C.DB.DB, &NodeInfo, "SELECT node_id,sn,isp,public_ip,mac,history_online_time FROM mg_node "+
			" WHERE uid=? AND sn=? and `status` <>2 Limit 1", Uid, Keyword)
	case 2: //2:linux
		err = sqlx.Get(config.C.DB.DB, &NodeInfo, "SELECT node_id,sn,isp,public_ip,mac,history_online_time FROM mg_node "+
			" WHERE uid=? AND mac=? and `status` <>2 Limit 1", Uid, Keyword)
	case 3: //3:路由器
		err = sqlx.Get(config.C.DB.DB, &NodeInfo, "SELECT node_id,sn,isp,public_ip,mac,history_online_time FROM mg_node "+
			" WHERE uid=? AND sn=? and `status` <>2 Limit 1", Uid, Keyword)
	default:
		break
	}
	if err == sql.ErrNoRows {
		return NodeInfo, nil
	}
	if err != nil {
		return NodeInfo, err
	}
	return NodeInfo, nil
}

type NodeSpModel struct {
	City         string `db:"city" form:"city" json:"city"`
	Province     string `db:"province" form:"province" json:"province"`
	Country      string `db:"country" form:"country" json:"country"`
	ISP          string `db:"isp" form:"isp" json:"isp"`
	PublicIp     string `db:"public_ip" form:"public_ip" json:"public_ip"`
	PublicAccess int    `db:"public_access" form:"public_access" json:"public_access"`
}

// 更新新结点信息
func UpdateMgNodeInfo(NodeID int64, Sn, Mac, Ip, HistoryOnlineTime string, Status, Way, OnlineTime int, DiskAvail float64, isp NodeSpModel) (err error) {
	if NodeID <= 0 {
		return nil
	}
	diskAvailStr := e.ParseString(DiskAvail, 2)
	nodeIdStr := strconv.FormatInt(NodeID, 10)
	sqlStr := "UPDATE mg_node SET public_ip='" + Ip + "', sn='" + Sn + "', mac='" + Mac + "', online_status=" + strconv.Itoa(Status) + ", " +
		"online_time=" + strconv.Itoa(OnlineTime) + ", type=" + strconv.Itoa(Way) + ",storage_available=" + diskAvailStr +
		",history_online_time='" + HistoryOnlineTime + "',isp='" + isp.ISP + "',country='" + isp.Country + "',city='" + isp.City +
		"',province='" + isp.Province + "',update_time=NOW() WHERE node_id= " + nodeIdStr
	res := sqlx.MustExec(config.C.DB.DB, sqlStr)
	ra, err := res.RowsAffected()
	if err != nil {
		return errno.DbError
	}
	if ra == 0 {
		return nil
	}
	return nil
}

// 更新新结点运营商信息
func UpdateMgNodeIpsData(NodeID int64, Ip string, isp NodeSpModel) (err error) {
	if NodeID <= 0 {
		return nil
	}
	nodeIdStr := strconv.FormatInt(NodeID, 10)
	sqlStr := "UPDATE mg_node SET public_ip='" + Ip + "',isp='" + isp.ISP + "',country='" + isp.Country + "',city='" +
		isp.City + "',province='" + isp.Province + "',update_time=NOW() WHERE node_id= " + nodeIdStr
	res := sqlx.MustExec(config.C.DB.DB, sqlStr)
	ra, err := res.RowsAffected()
	if err != nil {
		return errno.DbError
	}
	if ra == 0 {
		return nil
	}
	return nil
}

// 节点 运营商的信息
func GetISPByIp(Ip string) (res NodeSpModel, err error) {

	region, err := ip2region.New("./conf/ip2region.db")
	defer region.Close()
	if err != nil {
		return res, err
	}
	ip, err := region.MemorySearch(Ip)
	if err != nil {
		return res, err
	}

	res.City = ip.City
	res.Country = ip.Country
	res.ISP = ip.ISP
	res.Province = ip.Province
	return res, nil
}

// 更新内网Ip显示
func UpdateMgNodeLocalIp(NodeID int64, localIp, clientIp string) (err error) {
	if NodeID <= 0 {
		return nil
	}
	res := sqlx.MustExec(config.C.DB.DB, "UPDATE mg_node SET local_ip=?, public_ip =? WHERE node_id=? ", localIp, clientIp, NodeID)
	ra, err := res.RowsAffected()
	if err != nil {
		return errno.DbError
	}
	if ra == 0 {
		return nil
	}
	return nil
}

// 获取到 更新节点流量数据的sql
func GetUpdateNodeFlowSql(NodeID int64, Up float64, Way, Source int, Time int64) (sql string) {
	nodeIdStr := strconv.FormatInt(NodeID, 10)
	upStr := e.ParseString(Up, 8)
	timeStr := strconv.FormatInt(Time, 10)
	wayStr := strconv.Itoa(Way)
	sourceStr := strconv.Itoa(Source)
	sql = "(" + nodeIdStr + ", " + upStr + "," + wayStr + "," + timeStr + ", 0, " + sourceStr + ")"
	return sql
}

// 获取到 更新节点流量数据的sql
func BatchUpdateNodeFlowSql(sqlListString []string) (err error) {
	if len(sqlListString) < 1 {
		return
	}
	sqlStr := "REPLACE INTO mg_node_flow (node_id, up, type, time, status, source) VALUES " + strings.Join(sqlListString, ",") + ";"
	res := sqlx.MustExec(config.C.DB.DB, sqlStr)
	ra, err := res.RowsAffected()
	if err != nil {
		return errno.DbError
	}
	if ra == 0 {
		return nil
	}
	return nil
}

// 校验是否该节点流量数据已更新
func CheckNodeFlowUpdateByTime(NodeId, Hour int64, Way int) (err error) {
	var count int
	err = sqlx.Get(config.C.DB.DB, &count, "SELECT count(*) FROM mg_node_flow WHERE node_id=? AND time=? AND `type`=?", NodeId, Hour, Way)
	if err != nil {
		return err
	}
	if count > 0 {
		return nil
	}
	return errno.RecordError
}

// 获取所以需要结算的UID信息
func GetMgNodeInfoForRedis() (res []MgNodeInfoResponse, err error) {
	err = sqlx.Select(config.C.DB.DB, &res, "SELECT node_id, mac, sn, uid, type, history_online_time,token_status,batch FROM mg_node WHERE `status` = 1")
	if err != nil {
		return res, err
	}

	return
}

// 获取所有需要结算节点的信息
func GetNodesInfoForRedis(Uid int64, Type int) (res []MgUserProfitsResponse, err error) {
	err = sqlx.Select(config.C.DB.DB, &res, "select t1.uid as uid, t1.batch as batch, t1.node_id as node_id, IFNULL(SUM(t2.up) /1024/1024, 0.00) AS up "+
		" from mg_node as t1 left join mg_node_flow as t2 on t1.node_id = t2.node_id and t2.time >= UNIX_TIMESTAMP(CURDATE()) and t2.`status` = 0 "+
		" where t1.uid = ? AND t1.type= ? AND t1.token_status > 1 "+
		" group by t1.uid, t1.node_id ", Uid, Type)
	if err != nil {
		return res, err
	}
	return
}

// 获取到结点信息
func GetSingleNodeInfoForRedis(NodeId int64) (res MgNodeInfoResponse, err error) {
	err = sqlx.Get(config.C.DB.DB, &res, "SELECT node_id, mac, sn, uid, type, history_online_time,token_status,batch "+
		" FROM mg_node WHERE node_id = ? ", NodeId)
	if err != nil {
		return res, err
	}
	return res, nil
}

// 获取所以需要结算的UID信息
func GetUnMgNodeInfoForRedis(NodeId int64, Show int) (flow float64, err error) {

	if Show == 1 {
		err = sqlx.Get(config.C.DB.DB, &flow, "SELECT IFNULL( SUM(up) / 1024/ 1024, 0.00 ) FROM mg_node_flow "+
			" WHERE `status` = 0 AND time < UNIX_TIMESTAMP(CURDATE()) AND node_id = ?", NodeId)
	} else {
		err = sqlx.Get(config.C.DB.DB, &flow, "SELECT IFNULL( SUM(up) / 1024/ 1024, 0.00 ) FROM mg_node_flow "+
			" WHERE `status` = 0 AND time >= UNIX_TIMESTAMP(CURDATE()) AND node_id = ?", NodeId)
	}

	if err != nil {
		return flow, err
	}

	return
}

// 写入待结算记录表
func AddMgNodePaymentRecord(NodeData CheckNodeInfoResponse) (err error) {

	// 开启事务
	conn, err := config.C.DB.DB.Begin()
	if err != nil {
		return err
	}

	var rowId1, rowId2 int64
	// 汇总流量数据以用户纬度
	Cvn9 := e.ParseString(0.9*NodeData.Cvn, 8)
	Cvn1 := e.ParseString(0.1*NodeData.Cvn, 8)
	r1, err1 := conn.Exec("REPLACE INTO mg_node_payment (date, uid, node_id, up, type, pledge_status, "+
		"status,cvn,super_cvn,super_node_id,online_time,create_time) VALUES (?,?,?,?,?,?,?,?,?,?,?,unix_timestamp(NOW())) ",
		NodeData.DateStr, NodeData.Uid, NodeData.NodeId, NodeData.Up, NodeData.Type, NodeData.PledgeStatus, NodeData.IncomeMode,
		Cvn9, Cvn1, NodeData.SuperNodeId, NodeData.OnlineTime)
	if err1 == nil {
		rowId1, err = r1.RowsAffected()
		if err != nil {
			return errno.DbError
		}
	}

	// 将流量数据状态更新为 待结算
	r2, err2 := conn.Exec("UPDATE mg_node_flow SET status = 1 WHERE time < unix_timestamp(NOW()) AND status = 0 "+
		" AND node_id = ? AND type = ?", NodeData.NodeId, NodeData.Type)
	if err2 == nil {
		rowId2, err2 = r2.RowsAffected()
		if err2 == nil {
			rowId2 = 1
		}
	}

	// 提交事务
	if rowId1 > 0 && rowId2 > 0 && err2 == nil {
		err = conn.Commit()
		if err != nil {
			_ = conn.Rollback()
			return errno.RollBackErr
		}
		e.Log("info", "统计完成【结点汇总阶段】.")
		return nil
	} else {
		_ = conn.Rollback()
		return errno.RollBackErr
	}
}

// 写记录到user_payment表
func AddMgUserPayment() (err error) {

	e.Log("info", "准备发放数据【准备发放阶段】...")

	// 开启事务
	conn, err := config.C.DB.DB.Begin()
	if err != nil {
		return err
	}
	var rowId1, rowId2 int64

	// 更新汇总记录
	r2, err2 := conn.Exec("REPLACE INTO `lx_cvn_day_count` (`mining_time`, `size`, `cvn`, `create_time`) " +
		" SELECT DATE_SUB(CURDATE(),INTERVAL 1 DAY), IFNULL(SUM(up), 0.00), IFNULL(SUM(`cvn` + `super_cvn`), 0.00), UNIX_TIMESTAMP(NOW()) FROM mg_node_payment " +
		" WHERE `date` = DATE_SUB(CURDATE(),INTERVAL 1 DAY) AND `status` = 1")
	if err2 == nil {
		rowId2, err2 = r2.LastInsertId()
		if err2 != nil {
			e.Log("err", "err2---2 !!!", err2.Error())
		}
		if rowId2 <= 0 {
			e.Log("err", "rowId2 !!! == ", rowId2)
		}
	} else {
		e.Log("err", "err2 !!!", err2.Error())
	}

	// 写入 mg_user_payment 表
	r1, err1 := conn.Exec("INSERT INTO mg_user_payment (`lx_count_id`, `uid`, `up`, `cvnt`, `status`, `create_time`, `date`, `type`) "+
		" SELECT ?, `uid`, SUM(`up`), IFNULL(SUM(`cvn`), 0.00), 2, UNIX_TIMESTAMP(NOW()), DATE_SUB(CURDATE(),INTERVAL 1 DAY), type FROM mg_node_payment WHERE "+
		" `date` = DATE_SUB(CURDATE(),INTERVAL 1 DAY) AND `status` = 1 GROUP BY uid, type ", rowId2)
	if err1 == nil {
		rowId1, err1 = r1.RowsAffected()
		if err1 != nil {
			e.Log("err", "err1---2 !!!", err1.Error())
		}
		if rowId1 <= 0 {
			e.Log("err", "rowId1 !!! == ", rowId1)
		}
	} else {
		e.Log("err", "err1 !!!", err1.Error())
	}

	// 提交事务
	if rowId1 > 0 && rowId2 > 0 && err1 == nil && err2 == nil {
		err = conn.Commit()
		if err != nil {
			_ = conn.Rollback()
			return errno.RollBackErr
		}
		e.Log("info", "准备发放完成【准备发放阶段】.")
		return nil
	} else {
		_ = conn.Rollback()
		return errno.RollBackErr
	}
}

// 获取到 待结算uid List
func GetMgPurchaseUserList() (re []UidList, err error) {

	err = sqlx.Select(config.C.DB.DB, &re, "SELECT uid FROM mg_user_payment WHERE status = 2 AND create_time >= UNIX_TIMESTAMP(CURDATE()) ")
	if err != nil {
		return re, err
	}
	return
}

func GetThirdRouterUserList() (re []UidList, err error) {

	err = sqlx.Select(config.C.DB.DB, &re, "SELECT uid FROM mg_user_payment WHERE status=2 AND type=4 AND create_time>=UNIX_TIMESTAMP(CURDATE()) ")
	if err != nil {
		return re, err
	}
	return
}

// 获取到 数据由uid
func GetMgUserPaymentByUid(Uid int64) (res []MgUserPaymentModel, err error) {

	err = sqlx.Select(config.C.DB.DB, &res, "SELECT id, uid, up, type, cvnt FROM mg_user_payment WHERE uid = ? AND "+
		" create_time >= UNIX_TIMESTAMP(CURDATE()) AND `status` = 2 order by cvnt DESC ", Uid)
	if err != nil {
		return res, err
	}
	return
}

// 获取用户累计收益
func GetMgUserLastPaymentByUid(Uid int64) (profit float64, err error) {
	err = sqlx.Get(config.C.DB.DB, &profit, "SELECT IFNULL(SUM(cvnt), 0.00) FROM mg_user_payment WHERE uid = ? "+
		" AND `status`=3 AND create_time > 1587571200", Uid)
	if err != nil {
		return profit, err
	}
	return profit, nil
}

func GetThirdRouterPaymentByUid(Uid int64) (res MgUserPaymentModel, err error) {

	err = sqlx.Get(config.C.DB.DB, &res, "SELECT id, uid, up, type, cvnt FROM mg_user_payment WHERE uid = ? AND "+
		" create_time >= UNIX_TIMESTAMP(CURDATE()) AND `status` = 2 AND type =4 Limit 1 ", Uid)
	if err != nil {
		return res, err
	}
	return
}

// Auth: hzp
func GetNodeIdByMac(mac string) (res NodeMacModel, err error) {
	db := config.C.DB.DB
	count := 0
	err = sqlx.Get(db, &count, "SELECT COUNT(*) AS record from mg_node where mac = ? AND `status` < 2 AND type=2 limit 1", mac)
	if err != nil || count <= 0 {
		res.Uid = 0
		res.NodeId = 0
		res.Name = ""
		return res, err
	}
	err = sqlx.Get(config.C.DB.DB, &res, "SELECT node_id, uid, name from mg_node where mac = ? AND `status` < 2 AND type=2 limit 1", mac)
	if err != nil {
		return res, err
	}
	return
}

func GetNodeByUidMacRecords(uid int64) (res int, err error) {

	err = sqlx.Get(config.C.DB.DB, &res, "SELECT count(*) from mg_node where uid = ?", uid)
	if err != nil {
		return res, err
	}
	return
}

func GetUserTokenCount(uid int64) (int, error) {
	db := config.C.DB.DB
	var count int
	err := sqlx.Get(db, &count, "select count(*) from user_token where uid = ?", uid)
	if err != nil {
		return 0, err
	}
	return count, nil
}

func DeleteUserToken(uid int64, limitNum int) error {
	db := config.C.DB.DB
	res, err := db.Exec("DELETE FROM user_token WHERE uid = ? ORDER BY dateline ASC LIMIT ?", uid, limitNum)
	if err != nil {
		return err
	}
	ra, err := res.RowsAffected()
	if err != nil {
		return errors.Wrap(err, "get rows affected error")
	}
	if ra == 0 {
		return errors.New("not exist")
	}
	return nil
}

// 获取指定日期的Gbps
type dateGbpsStruct struct {
	TT   string  `json:"tt" db:"tt"`
	Gbps float64 `json:"gbps" db:"gbps"`
}

func GetTheDateGbps(star, end int64, Source int) (gbps float64, err error) {
	db := config.C.DB.DB
	var res dateGbpsStruct
	if Source > 0 {
		err = sqlx.Get(db, &res, "SELECT FROM_UNIXTIME(`time`, '%Y-%m-%d %H') AS tt, "+
			" (IFNULL( SUM(up), 0) * 8/ 3600 / 1024/ 1024) AS gbps FROM mg_node_flow WHERE `time` >= ? "+
			" AND `time` <= ? AND source = ? GROUP BY tt DESC ORDER BY gbps DESC LIMIT 1", star, end, Source)
	} else {
		err = sqlx.Get(db, &res, "SELECT FROM_UNIXTIME(`time`, '%Y-%m-%d %H') AS tt, "+
			" (IFNULL( SUM(up), 0) * 8/ 3600 / 1024/ 1024) AS gbps FROM mg_node_flow WHERE `time` >= ? "+
			" AND `time` <= ? GROUP BY tt DESC ORDER BY gbps DESC LIMIT 1", star, end)
	}
	if err != nil {
		if err == sql.ErrNoRows {
			return 0.00, nil
		} else {
			return 0, err
		}
	}
	if res.Gbps > 0 {
		gbps = res.Gbps
	} else {
		gbps = 0.00
	}
	return gbps, nil
}

// 获取指定日期的总流量
func GetTheDateTotalFlows(start, end int64, Source int) (flows int64, err error) {
	db := config.C.DB.DB
	err = sqlx.Get(db, &flows, "SELECT IFNULL(SUM(up), 0) AS flows FROM mg_node_flow WHERE "+
		" `time` >= ? AND `time` <= ? AND `source` =? ", start, end, Source)
	if err != nil {
		if err == sql.ErrNoRows {
			return 0.00, nil
		} else {
			return 0, err
		}
	}
	return flows, nil
}

type NetProfitResponse struct {
	SourceCvn   float64 `json:"source_cvn" db:"source_cvn"`
	SourceFlows int64   `json:"source_flows" db:"source_flows"`
}

// 获取指定日结算收益
func GetTheLastDateCdnProfit(DateStr string) (profit NetProfitResponse, err error) {

	err = sqlx.Get(config.C.DB.DB, &profit, " SELECT IFNULL( source_cvn, 0.00 ) as source_cvn, "+
		" IFNULL(source_flows, 0) as source_flows FROM mg_node_payment WHERE DATE = ? LIMIT 1", DateStr)
	if err != nil {
		return profit, err
	}
	return profit, nil
}

// 全网节点数 统计
// typeInt = 1 全网未删除的节点总数
// typeInt = 2 全网在线的节点总数
// typeInt = 3 全网昨日新增节点总数
func GetNodeNumsByType(typeInt int) (count int, err error) {

	db := config.C.DB.DB
	switch typeInt {
	case 1:
		err = sqlx.Get(db, &count, "SELECT COUNT(*) FROM mg_node WHERE `status` <> 2 AND "+
			" create_time > '2020-03-01 00:00:00'")
		break
	case 2:
		err = sqlx.Get(db, &count, "SELECT COUNT(*) FROM mg_node WHERE `status` = 1 AND "+
			" create_time > '2020-03-01 00:00:00'")
		break
	case 3:
		err = sqlx.Get(db, &count, "SELECT COUNT(*) FROM mg_node WHERE `status` <> 2 AND "+
			" create_time >= FROM_UNIXTIME(UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE) - INTERVAL 1 DAY)) AND "+
			" create_time < FROM_UNIXTIME(UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE)))")
		break
	default:
		break
	}

	if err != nil {
		return count, err
	}
	return count, nil
}

type GlobalSourceCheckRes struct {
	Name   string `json:"name"`
	Status int    `json:"status"`
}

type DailyBoardStruct struct {
	Date        string  `json:"date" db:"date"`
	NodeNums    int     `json:"node_nums" db:"node_nums"`
	OnlineNums  int     `json:"online_nums" db:"online_nums"`
	CreateNums  int     `json:"create_nums" db:"create_nums"`
	PledgeCvn   float64 `json:"pledge_cvn" db:"pledge_cvn"`
	UnPledgeCvn float64 `json:"unPledge_cvn" db:"unPledge_cvn"`
	Storage     float64 `json:"storage" db:"storage"`
	OutPut      float64 `json:"output" db:"output"`
}

// 插入看板数据
func AddDailyBoardData(res DailyBoardStruct) (err error) {
	rs := sqlx.MustExec(config.C.DB.DB, "INSERT INTO mg_daily_board(date,node_nums,online_nums,create_nums,"+
		"pledge_cvn,unPledge_cvn,storage,output) VALUES (DATE_SUB(CURDATE(),INTERVAL 1 DAY), ?, ?, ?, ?, ?, ?, ?)",
		res.NodeNums, res.OnlineNums, res.CreateNums, res.PledgeCvn, res.UnPledgeCvn, res.Storage, res.OutPut)
	r1, err := rs.LastInsertId()
	if err != nil {
		return err
	}
	if r1 > 0 {
		return nil
	}
	return errors.New("插入看板数据异常")
}

// 读取看板数据
// 不存在返回nil
func CheckDailyBoardByDate(date string) (err error) {
	db := config.C.DB.DB
	var count int
	err = sqlx.Get(db, &count, "SELECT count(*) FROM mg_daily_board WHERE `date` = ?")
	if err != nil {
		// 不存在返回nil
		return nil
	}
	if count < 0 {
		return nil
	}
	return errno.ExistsRecord
}

// 读取看板数据
func GetDailyBoardData(page, pageSize int) (count int, res []DailyBoardStruct, err error) {

	db := config.C.DB.DB
	err = sqlx.Get(db, &count, "SELECT count(*) FROM mg_daily_board WHERE 1")
	if err != nil {
		return count, res, err
	}
	start := (page - 1) * pageSize
	err = sqlx.Select(db, &res, "SELECT date,node_nums,online_nums,create_nums,pledge_cvn,unPledge_cvn,"+
		"storage,output FROM mg_daily_board Where 1 order by `date` desc limit ?, ?", start, pageSize)
	if err != nil {
		return count, res, err
	}
	return count, res, nil
}

// 最后更新时间小于今天12点之前，做离线一天处理
func DealOfflineNodeWithAfter12Hour() (count int64, err error) {
	res := sqlx.MustExec(config.C.DB.DB, "UPDATE mg_node SET online_time = 0, offline = offline + 1, process = process - 1"+
		" WHERE update_time < DATE_ADD(CURDATE(),INTERVAL 12 HOUR) AND process > 0")
	count, err = res.RowsAffected()
	if err != nil {
		return count, err
	}
	return count, nil
}

// 今晚23:59处理在线时长不超过12个小时，做离线一天处理
func DealOfflineNodeWithBlow12Hour() (count int64, err error) {
	res := sqlx.MustExec(config.C.DB.DB, "UPDATE mg_node SET offline = offline + 1, process = process - 1"+
		" WHERE update_time > DATE_ADD(CURDATE(),INTERVAL 12 HOUR) AND online_time < 715")
	count, err = res.RowsAffected()
	if err != nil {
		return count, err
	}
	return count, nil
}

// 更新节点为非质押节点
func UpdateMgNodeUnPledge(NodeId int64) (err error) {
	res := sqlx.MustExec(config.C.DB.DB, "UPDATE mg_node SET token_status = 1, token_id = 0, "+
		" pledge_time = UNIX_TIMESTAMP(NOW()) WHERE node_id = ? AND token_status = 3", NodeId)
	r1, err := res.RowsAffected()
	if err != nil {
		return err
	}
	if r1 <= 0 {
		return errno.RecordError
	}
	return nil
}

// 删除节点
func UpdateMgNodeOffline(NodeId int64) (err error) {
	res := sqlx.MustExec(config.C.DB.DB, "UPDATE mg_node SET `status` = 2 WHERE node_id = ?", NodeId)
	r1, err := res.RowsAffected()
	if err != nil {
		return err
	}
	if r1 <= 0 {
		return errno.RecordError
	}
	return nil
}

// 解除质押数据
func GetUnPledgeNodeNum() (nums float64, err error) {
	db := config.C.DB.DB
	err = sqlx.Get(db, &nums, "SELECT count(*) FROM mg_node WHERE token_status = 3 and "+
		" pledge_time >= UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE) - INTERVAL 1 DAY) AND "+
		" pledge_time < UNIX_TIMESTAMP(CAST(SYSDATE()AS DATE)) ")
	if err != nil {
		return nums, err
	}
	return nums, nil
}

// 获取全网总存储
func GetNetStorage() (storage float64, err error) {
	db := config.C.DB.DB
	err = sqlx.Get(db, &storage, "SELECT SUM(storage_available) / 1024 FROM mg_node WHERE `type` = 2 AND `status` <> 2 ")
	if err != nil {
		return storage, err
	}
	return storage, nil
}
